#pragma once

#include <vex/core/contract/handle.h>
#include <vex/functional/contract/delegate.h>
#include <vex/functional/result.h>

namespace vex { namespace functional { namespace contract {
    /// <summary>
    /// Abstraction for an ability to add and remove an delegate with given <c>TSignature</c>
    /// to and from an invocation list of some multicast service but not to invoke it. 
    /// The signatures of the connected types must be identical. Implementations
    /// are required to provide full thread safety guarantees for adding and removal
    /// of delegates. 
    /// </summary>
    ///
    /// Use this contract in contracts exposed to client code to expose an endpoint of multicast service.
    /// In order to support this scenario, <c>event</c> does not extend <c>core::contract::handle</c>,
    /// so that clients of your contract cannot take ownership or otherwise manipulate the <c>event</c>.
    template<class TSignature>
    struct VEX_ABSTRACT event {
        typedef delegate<TSignature> delegate_type;

        /// <summary>
        /// Add delegate to service. Returns true if successful, false otherwise.
        /// Implementations are required to provide full thread-safety guarantees.
        /// </summary>
        ///
        /// <param name="p_delegate">delegate instance to register</param>
        virtual bool add(delegate<TSignature>* p_delegate) = 0;

        /// <summary>
        /// Remove delegate from service. Returns true if successful, false otherwise.
        /// Implementations are required to provide full thread-safety guarantees.
        /// </summary>
        ///
        /// <param name="p_delegate">delegate instance to remove</param>
        virtual bool remove(delegate<TSignature>* p_delegate) = 0;

        VEX_PROTECT_CONTRACT(event);
    };
}}}